package org.jingouzhui.domain.strategy.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jingouzhui.domain.strategy.model.entity.RaffleAwardEntity;
import org.jingouzhui.domain.strategy.model.entity.RaffleFactorEntity;
import org.jingouzhui.domain.strategy.repository.IStrategyRepository;
import org.jingouzhui.domain.strategy.service.armory.IStrategyDispatch;
import org.jingouzhui.domain.strategy.service.rule.chain.factory.DefaultLogicChainFactory;
import org.jingouzhui.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import org.jingouzhui.types.enums.ResponseCode;
import org.jingouzhui.types.exception.AppException;
import org.springframework.stereotype.Service;

/**
 * @description: 抽奖策略抽象类  定义模板 提供抽象方法
 * @author: jingouzhui
 * @date: 2025/4/26 23:36
 */

@Slf4j
@Service
public abstract class AbstractRaffleStrategy implements IRaffleStrategy,IRaffleStock {


    protected IStrategyRepository strategyRepository;

    protected IStrategyDispatch strategyDispatch;

    protected DefaultLogicChainFactory defaultLogicChainFactory;

    protected DefaultTreeFactory defaultTreeFactory;

    public AbstractRaffleStrategy(IStrategyRepository strategyRepository,IStrategyDispatch strategyDispatch, DefaultLogicChainFactory defaultLogicChainFactory,DefaultTreeFactory defaultTreeFactory) {
        this.strategyRepository = strategyRepository;
        this.strategyDispatch = strategyDispatch;
        this.defaultLogicChainFactory = defaultLogicChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }


    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactor) {
        //1. 参数校验
        String userId = raffleFactor.getUserId();
        Long strategyId = raffleFactor.getStrategyId();
        if (StringUtils.isEmpty(userId) || strategyId == null) {
            throw  new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        // 2. 责任链抽奖计算【这步拿到的是初步的抽奖ID，之后需要根据ID处理抽奖】注意；黑名单、权重等非默认抽奖的直接返回抽奖结果
        DefaultLogicChainFactory.StrategyAwardVO strategyAwardVO = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, strategyAwardVO.getAwardId(), strategyAwardVO.getLogicModel());
        if (!DefaultLogicChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(strategyAwardVO.getLogicModel())) {
            //会被直接终止掉
            return  RaffleAwardEntity
                    .builder()
                    .strategyId(strategyId)
                    .awardId(strategyAwardVO.getAwardId())
                    .build();
        }
        // 3. 规则树抽奖过滤【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
        DefaultTreeFactory.StrategyAwardVO strategyTreeAwardVO = raffleLogicTree(userId, strategyId, strategyAwardVO.getAwardId());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, strategyTreeAwardVO.getAwardId(), strategyTreeAwardVO.getAwardRuleValue());


        return RaffleAwardEntity
                .builder()
                .strategyId(strategyId)
                .awardConfig(strategyTreeAwardVO.getAwardRuleValue())
                .awardId(strategyTreeAwardVO.getAwardId())
                .build();
    }


    /**
     * 抽奖计算，责任链抽象方法
     *
     * @param userId     用户ID
     * @param strategyId 策略ID
     * @return 奖品ID
     */
    public abstract DefaultLogicChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    /**
     * 抽奖结果过滤，决策树抽象方法
     *
     * @param userId     用户ID
     * @param strategyId 策略ID
     * @param awardId    奖品ID
     * @return 过滤结果【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId);

}
